﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Coding4Fun.BoxingBots.Common;

namespace Coding4Fun.BoxingBots.Communication
{
	public class SocketListener<TSend, TReceive>	where TSend : GamePacket
													where TReceive : GamePacket, new()
	{
		private readonly SynchronizationContext _context;

		private TcpListener _listener;
		private SocketClient<TSend,TReceive> _client;

		public event EventHandler<ConnectionEventArgs> ConnectionCompleted;
		public event EventHandler<PacketReceivedEventArgs<TReceive>> PacketReceived;

		public SocketListener()
		{
			_context = SynchronizationContext.Current;
		}
		
		public void Start(int port)
		{
			_listener = new TcpListener(IPAddress.Any, port);
			_listener.Start();
			_listener.BeginAcceptTcpClient(OnConnection, null);
		}

		private void OnConnection(IAsyncResult ar)
		{
			TcpClient client = _listener.EndAcceptTcpClient(ar);
			_client = new SocketClient<TSend,TReceive>(client);
			_client.PacketReceived += ClientPacketReceived;

			_listener.BeginAcceptTcpClient(OnConnection, null);

			ConnectionEventArgs args = new ConnectionEventArgs { Connected = _client.IsConnected };
			EventHelper.RaiseEvent(this, _context, ConnectionCompleted, args);
		}

		void ClientPacketReceived(object sender, PacketReceivedEventArgs<TReceive> e)
		{
			EventHelper.RaiseEvent(this, _context, PacketReceived, e);
		}

		public void Send(TSend packet)
		{
			if(_client != null)
				_client.Send(packet);
		}
	}
}
